/**
 * D5Power Studio d5power Webgame Engine
 *
 * Extends DOTK system
 * Author: D5Power Studio
 *
 *
 * 第五动力工作室 d5power网页游戏引擎 Ver 1.0
 * 继承自:DOTK引擎
 * 作者：第五动力工作室
 */

/* -------------------------------------------------------
 * DotK WebGame Engine, Version 0.5 Beta
 * DotK Engine is part of Defenders of the Kingdom's Project
 * Developer: Marcio Henrique Toloi
 * Date: 7-october-2007
 * ------------------------------------------------------- */

//Global variables.
var myCharacter = null;
var charactersOnScreen = [];
var monstersOnScreen=[];
var actualMap = null;
var mapOffset = {x:0, y:0};
var mLoop = null;
var eventsLoop = null;
var monsterLoop = null;

var allowClick = true;
var ctrlholded = false;
var lastOpponentClicked = '';
var rival = undefined; // 对手

var GADX = 40; // 区块总数
var GADY = 30;


function attack()
{

}

function defend() {

}

function keyDown(ev) {
	ev = ev || window.event;          // gets the event in ie or ns
	kCode = ev.keyCode || ev.which;   // gets the keycode in ie or ns
	// CTRL
	if (kCode == 17)
	{
		ctrlholded = true;
	}else {

	}
}

function keyUp(ev) {
  ev = ev || window.event;          // gets the event in ie or ns
  kCode = ev.keyCode || ev.which;   // gets the keycode in ie or ns

  if (kCode == 17) {
    ctrlholded = false;
  }
}

function keyPress(ev) {
  ev = ev || window.event;          // gets the event in ie or ns
  kCode = ev.keyCode || ev.which;   // gets the keycode in ie or ns

  if (kCode == 27) {
    $('ingame_menu').style.display = 'none';
  }
}
/*
* Interface functions
*/
function showIngameMenu(event) {

}

/**
 *	Leave Game Funciton
 *	
 *	
 */
function leaveGame() {
  if(myCharacter.busy || myCharacter.walking) {
    //dialog('alert',"You are busy and can't leave the game now. Please, try again soon.");
    //return;
  }
  else {
    new Ajax.Request(
            'd5power.php', {
            method: 'get',
            parameters: 'action=leaveGame',
            onComplete: function(result) {
              if(result.responseText == 'OK') {
                window.location = 'select_character.php';
              }
              else {
                gameConsole(responseText);
              }
              return;
            }});
  }
  return;
}

/**
 * Dotk Map Class
 */
Map = Class.create();
Map.prototype = {
  initialize: function() {
    this.mapId = undefined;
    this.collisionPoints = undefined;
    this.mapLayers = new Array('terrain_layer','ground_layer','up_layer');
    this.imgObjs = undefined;
    this.loadedImages = 0;
    this.totalImages = this.mapLayers.length;
	this.waypoints = null;
  },
    
  load: function() {
    this.imgObjs = new Array();
    $('loading').style.display = 'inline';
    for (var i=0; i<this.totalImages; i++) {
      this.imgObjs[i] = new Image();
      this.imgObjs[i].onload = this.imgLoaded;
      //imgObjs[i].onerror = imgFailed;
      this.imgObjs[i].src = 'd5power.php?action=loadMap&maplayer='+this.mapLayers[i]+"&rand="+Math.random();
      $(this.mapLayers[i]).style.backgroundImage = 'url("'+this.imgObjs[i].src+'")';
    }
    this.getCollisionPoints();
	this.getWaypoints();
	this.getNpc();
	this.getMonster();
  },

  
  imgLoaded: function() {
    actualMap.loadedImages++;
      if (actualMap.loadedImages == actualMap.totalImages) {
        $('loading').style.display = 'none';  
      }
    return;
  },
  	getNpc:function(){
		new Ajax.Request(
		'd5power.php', {
		method: 'get',
		parameters: 'action=loadNpc',
		onComplete: function(result) {
			var npc_data = eval("(" + result.responseText + ")");
			npcList = new Array();
			
			for(var i=0;i<npc_data.length;i++)
			{
				var pos = tileToPixel([npc_data[i].posx,npc_data[i].posy]);
				npcList.push(new NPC(npc_data[i].npc_id,npc_data[i].npc_name,pos,npc_data[i].avatar));
			}
			//var monsterList = new Array();
			//monsterList.push(new Monster('12','波利',pos,'boli'));
		}});
		return;
	},
	
	getMonster:function(){
		new Ajax.Request(
			'd5power.php',
			{
				method: 'get',
				parameters: 'action=loadMonster',
				onComplete: function(result)
							{
								var monster_data = eval("(" + result.responseText + ")");
								monsterBirth(monster_data);
							}
			}				 
		);
		return;
	},
  getWaypoints: function() {
    new Ajax.Request(
            'd5power.php', {
            method: 'get',
            parameters: 'action=load_waypoints',
            onComplete: function(result) {
              actualMap.waypoints = new Waypoint();
              actualMap.waypoints.load(eval("(" + result.responseText + ")"));
            }});
    return;
  },
  
  loadCollisionMap: function() {
    var url = 'getMapInfo.php';
    var pars = 'colisionMap=1';
    var myAjax = new Ajax.Request( url, { method: 'get', parameters: pars, onComplete: 
            function(result) {
                this.collisionPoints = this.parseCollisionPoints();
            } });
  },
    
  getCollisionPoints: function() {
    new Ajax.Request(
            'd5power.php', {
            method: 'get',
            parameters: 'action=loadCollisionPoints',
            onComplete: function(result) {
                            actualMap.collisionPoints = eval("(" + result.responseText + ")");						
            }});
    return;
  }
};


/**
 * Players List Class
 * Structure to handle character instances.
 */
characterList = Class.create();
characterList.prototype = {
  initialize: function() {
    this.list = [];
  },

  add: function(characterInstance) {
    this.list.push(characterInstance);
    return;
  },
  
  length: function() {
    return this.list.length;
  },

  remove: function(characterId) {
    for (i=0; i<this.list.length; i++) {
      if (this.list[i].characterId == characterId) {
        this.list[i].destroy();
        this.list[i] = null; 
      }
    }
    this.list = this.list.compact();	
    return;
  },

  getById: function(characterId) {
    for (i=0; i<this.list.length; i++) {
      if (this.list[i].characterId == characterId) {
        return this.list[i];
      }
    }
    return null;
  },
  
  getByIndex: function(index) {
    return this.list[index];
  }
};


/**
 * Player Class
 * No implementations was needed for while.
 */
Player = Class.create();
Player.prototype = {
  //void    
};

/**
 *	NPC Class
 *	By D5Power Studio
 *	This is not extend from dotk
 */
NPC = Class.create();
NPC.prototype = {
		initialize:function(npcId,name,actualPosition,avatar)
		{
			this.npcId = npcId;
			this.name = name;
			this.actualPosition = actualPosition;
			this.avatar = avatar;
			
			this.charWidth = 32;
			this.charHeight = 48;
			
			//Configuring character container (div)
			this.charContainer = document.createElement('DIV');
			this.charContainer.id = "NPC"+this.npcId;
			this.charContainer.className = 'npc';
			this.charContainer.innerHTML = "<img src = \"..\/pictures\/npc\/"+ this.avatar +".gif\">";
			$('characters_layer').appendChild(this.charContainer);
			
			//Configuring character's name container (div)
			this.charLabelContainer = document.createElement('DIV');
			this.charLabelContainer.id = "NPC"+this.npcId+'Label';
			this.charLabelContainer.className = 'npcLabel';
			this.charLabelContainer.innerHTML = '<div style="position: absolute; top: 1px; left: 1px; color: #000;">'+ this.name + '</div>';
			this.charLabelContainer.innerHTML += '<div style="position: absolute; top: 0px; left: 0px;color:#FF9900">'+ this.name + '</div>';
			$('up_layer').appendChild(this.charLabelContainer);
			
			//Configuring character container (div)
			this.charEventDiv = document.createElement('DIV');
			this.charEventDiv.id = this.npcId;
			this.charEventDiv.name = this.name;
			this.charEventDiv.avatar = this.avatar;
			this.charEventDiv.className = 'npc';
			
			if(document.addEventListener)
			{
				this.charEventDiv.addEventListener('click',callNpcEvent,true);
				this.charEventDiv.addEventListener('onmouseover',function(){allowClick=false;},true);
				this.charEventDiv.addEventListener('onmouseout',function(){allowClick=true;},true);
			}else{
				this.charEventDiv.attachEvent('onclick',callNpcEvent);
				this.charEventDiv.attachEvent('onmouseover',function(){allowClick=false;});
				this.charEventDiv.attachEvent('onmouseout',function(){allowClick=true;});
			}
			$('events_layer').appendChild(this.charEventDiv);
			
			this.moveLayers(this.actualPosition.x,this.actualPosition.y);
		},
		
		moveLayers: function(newPoint_x, newPoint_y)
		{
			this.charContainer.style.left = (newPoint_x - this.charWidth/2)+"px";
			this.charContainer.style.top = (newPoint_y - this.charHeight)+"px";
			this.charEventDiv.style.left = (newPoint_x - this.charWidth/2)+"px";
			this.charEventDiv.style.top = (newPoint_y - this.charHeight)+"px";
			this.charLabelContainer.style.left = (newPoint_x-40)+"px";
			this.charLabelContainer.style.top = (newPoint_y-2)+"px";
			return;
    	}
	
	};

/**
 * Generic Character Class
 */
Character = Class.create();
Character.prototype = {
    initialize: function(characterId,name,actualPosition,pictureKind,gender,hp,str,dex,int,vit,agi,atk,def,lv,xp) {
        this.characterId = characterId;
        this.name = name;
        this.actualPosition = actualPosition;
        this.pictureKind = pictureKind+"_"+gender;
        this.pictureNum = 2;
        this.walking = false;
        this.lookingTo = 'south';
        this.speed = 4;		// 2/4测试通过
        this.pointsToWalk = [];
		this.busy = false;
		this.changeMap = false;
		this.hp = hp;
		this.gender = gender;
		this.lv = lv;
		this.atk = atk;
		this.def = def;
		this.str = str;
		this.dex = dex;
		this.int = int;
		this.vit = vit;
		this.agi = agi;
		this.xp = xp;
		
		this.charWidth = 32;
		this.charHeight = 48;
		
		

        //Configuring character container (div)
        this.charContainer = document.createElement('DIV');
        this.charContainer.id = this.characterId;
        this.charContainer.className = 'character';
        $('characters_layer').appendChild(this.charContainer);
		
		//Configuring face container(div)
		this.faceBox = document.createElement('DIV');
		this.faceBox.id = "faceBox"+this.characterId;
		this.faceBox.className = 'faceBox';
		$('up_layer').appendChild(this.faceBox);
		
		//Configuring chat container(div)
		this.chatBox = document.createElement('DIV');
		this.chatBox.id = "chatBox"+this.characterId;
		this.chatBox.className = 'chatBox';
		$('up_layer').appendChild(this.chatBox);
		
		//Configuring character's name container (div)
        this.charLabelContainer = document.createElement('DIV');
        this.charLabelContainer.id = this.characterId+'Label';
        this.charLabelContainer.className = 'charLabel';
        this.charLabelContainer.innerHTML = '<div style="position: absolute; top: 1px; left: 1px; color: #000;">'+ this.name + '</div>';
        this.charLabelContainer.innerHTML += '<div style="position: absolute; top: 0px; left: 0px;">'+ this.name + '</div>';
        $('up_layer').appendChild(this.charLabelContainer);
		
		this.charEventDiv = document.createElement('DIV');
        this.charEventDiv.id = this.characterId;
        this.charEventDiv.className = 'character';
		$('events_layer').appendChild(this.charEventDiv);
		
		// 调整位置
		this.moveLayers(this.actualPosition.x,this.actualPosition.y);

		
		if (document.addEventListener)
		{
        	this.charEventDiv.addEventListener("click", showIngameMenu, true);
        }else if (document.attachEvent){
        	this.charEventDiv.attachEvent("onclick", showIngameMenu);
        }
		
        	
        setTimeout('charactersOnScreen.getById('+this.characterId+').logOnAnimation()',200);
        return;
    },

    destroy: function() {
        $('characters_layer').removeChild(this.charContainer);
        $('up_layer').removeChild(this.charLabelContainer);
		$('events_layer').removeChild(this.charEventDiv);
		$('up_layer').removeChild(this.chatBox);
		$('up_layer').removeChild(this.faceBox);
        return;
    },

    lookTo: function(direction) {
        switch (direction) {
            case 'EAST': this.lookingTo = 'east'; break;
            case 'WEST': this.lookingTo = 'west'; break;
            case 'NORTH': this.lookingTo = 'north'; break;
            case 'SOUTH': this.lookingTo = 'south'; break;
        }
        return;
    },

    logOnAnimation: function() {
        this.charContainer.innerHTML = "<img src = \"..\/pictures\/chipsets\/logoff.gif\">";
        this.pictureNum = 1;
        setTimeout('charactersOnScreen.getById('+this.characterId+').changePicture()',600);
        return;
    },

    logOffAnimation: function() {
        this.charContainer.innerHTML = "<img src = \"..\/pictures\/chipsets\/logoff.gif\">";
        return;
    },

    moveLayers: function(newPoint_x, newPoint_y) {
        this.charContainer.style.left = (newPoint_x - this.charWidth/2)+"px";
        this.charContainer.style.top = (newPoint_y - this.charHeight)+"px";
		this.chatBox.style.left = (newPoint_x - this.charWidth/2)+"px";
		this.chatBox.style.top = (newPoint_y - this.charHeight - 20)+"px";
		this.faceBox.style.left = (newPoint_x - this.charWidth/2-20)+"px";
		this.faceBox.style.top = (newPoint_y - this.charHeight - 20)+"px";
		this.charEventDiv.style.left = (newPoint_x - this.charWidth/2)+"px";
        this.charEventDiv.style.top = (newPoint_y - this.charHeight)+"px";
        this.charLabelContainer.style.left = (newPoint_x - 55)+"px";
        this.charLabelContainer.style.top = (newPoint_y)+"px";
        return;
    },
	
	setupUserinfo:function()
	{
		$('characterHead').src='../pictures/chipsets/'+this.pictureKind+'.gif';
		$('equipmentMyAvtara').src='../pictures/chipsets/'+this.pictureKind+'_full.gif';
		$('characterLv').innerHTML = this.lv;
		$('characterName').innerHTML = this.name;
		
		// 基本宽度（用于计算HP和EXP的显示）
		baseWidth = parseInt($('characterBar').style.width);
		
		nextExp = this.getNextLevelExp(parseInt(this.lv)+1);
		expWidth = Math.floor(baseWidth*this.xp/nextExp);
		$('characterEXP').style.width = expWidth+'px';
		$('characterBar_exp').title=this.xp+'/'+nextExp;
		
		baseHp = this.getMaxHp();
		hpWidth = Math.floor(baseWidth*this.hp/baseHp);
		$('characterHP').style.width = hpWidth+'px';
		$('characterBar').title=this.hp+'/'+baseHp;
		
		baseAtk = monsterFightBaseAtk(this.lv,this.str);
		$('characterATK').innerHTML = baseAtk+'+'+this.atk;
		
		baseDef = monsterFightBaseDef(this.lv,this.vit);
		$('characterDEF').innerHTML = baseDef+'+'+this.def;
		
		$('characterSTR').innerHTML = this.str;
		$('characterINT').innerHTML = this.int;
		$('characterAGI').innerHTML = this.agi;
		$('characterDEX').innerHTML = this.dex;
		$('characterVIT').innerHTML = this.vit;
	},
	
	getNextLevelExp:function(level)
	{
		return (50 * level + Math.pow(level,4));
	},
	
	getMaxHp:function()
	{
		return (40*this.lv + Math.pow(Math.floor(this.vit/6),3));
	},

    changePicture: function() {
        this.pictureNum++;  
        if (this.pictureNum > 4) {
            this.pictureNum = 1;
        }  
        this.charContainer.innerHTML = "<img src = \"..\/pictures\/chipsets\/"+ this.pictureKind + "_" + this.lookingTo + this.pictureNum + ".gif\">";
    },

    walk : function() {
        if(this.walking) {
            var alreadyLooking = false;
            var target = tileToPixel(this.pointsToWalk[0]);
            if(target.x == this.actualPosition.x && target.y == this.actualPosition.y) {
                this.pointsToWalk.shift();
                if(this.pointsToWalk.length == 0) {
                    this.walking = false;
                    this.pictureNum = 1;
                    this.changePicture();
					if(this.changeMap)
					{
                    	changeMap();
                  	}
					// 怪物战斗判断开始
					if(walk_to_monster!=null)
					{
						chaX = Math.abs(this.actualPosition.x-walk_to_monster.actualPosition.x);
						chaY = Math.abs(this.actualPosition.y-walk_to_monster.actualPosition.y);

						if(chaX<=this.charWidth*2 && chaY<=this.charHeight*2)
						{
							// monster.js
							fightWithMonster();
						}else{
							//walk_to_monster=null;
						}
					}
                    return;
                }
            }
            target = tileToPixel(this.pointsToWalk[0]);
            
            if(target.x > this.actualPosition.x) { 
                this.actualPosition.x += this.speed; 
                this.lookingTo = 'east';
                alreadyLooking = true;
            }
            else if(target.x < this.actualPosition.x) {
                this.actualPosition.x -= this.speed;
                this.lookingTo = 'west';
                alreadyLooking = true;
            }
            
            if(target.y > this.actualPosition.y) { 
                this.actualPosition.y += this.speed;
                if(!alreadyLooking) {
                    this.lookingTo = 'south';
                }
            }
            else if(target.y < this.actualPosition.y) { 
                this.actualPosition.y -= this.speed; 
                if(!alreadyLooking) {
                    this.lookingTo = 'north';
                }
            }
			
			this.changePicture();
        	this.moveLayers(this.actualPosition.x, this.actualPosition.y);
        }
    }
};


/**
 * Waypoint class
 */
Waypoint = Class.create();
Waypoint.prototype = {
  initialize : function() {
    this.waypoints = null;
    this.active = false;
    return;
  },

  load : function(waypoints) {
    this.waypoints = waypoints;
    for(var i=0; i<this.waypoints.length; i++)
	{
		var pos = tileToPixel({0:this.waypoints[i].x, 1:this.waypoints[i].y});
		var wp_div = document.createElement('DIV');
		wp_div.setAttribute('name','wp_div');
		wp_div.setAttribute('style','width: 16px; height: 16px; position: absolute; z-index:1; left: '+(pos.x - 8)+'px; top: '+(pos.y - 8)+'px;');
		if(wp_div.style.width==null || wp_div.style.width=='')
		{
			wp_div.style.width='16px';
			wp_div.style.height='16px';
			wp_div.style.position='absolute';
			wp_div.style.zIndex=1;
			wp_div.style.left = (pos.x - 8)+'px';
			wp_div.style.top = (pos.y - 8)+'px';
		}
		wp_div.onmouseover = function() {
		this.childNodes[0].setAttribute('width','16px');
		this.childNodes[0].setAttribute('height','16px');
	}

      wp_div.onmouseout = function() {
        this.childNodes[0].setAttribute('width','0px');
        this.childNodes[0].setAttribute('height','0px');
      };

      wp_div.onclick = function() {
        actualMap.waypoints.active = true;
      };

      var img = document.createElement('img');
      img.setAttribute('width','0px');
      img.setAttribute('height','0px;');
	  /*
      if(this.waypoints[i].x == 0) {
        img.setAttribute('src','../pictures/arrow_left.gif');
      }
      else if(this.waypoints[i].x == 39) {
        img.setAttribute('src','../pictures/arrow_right.gif');
      }
      else if(this.waypoints[i].y == 0) {
        img.setAttribute('src','../pictures/arrow_up.gif');
      }
      else if(this.waypoints[i].y == 29) {
        img.setAttribute('src','../pictures/arrow_down.gif');
      }
      else {
        img.setAttribute('src','../pictures/arrow_up.gif');
      }
	  */
	  img.setAttribute('src','../pictures/waypoint.gif');
      wp_div.appendChild(img);

      $('events_layer').appendChild(wp_div);
    }
    return;
  },

  isActive : function() {
    if(this.active) {
      return true;
    }
    else {
      return false;
    }
  },

  length : function() {
    return this.waypoints.length;
  }
}

/**
 * Function pixelToTile
 * @description Converts a coordinate in pixels to a coordinate in tiles.
 * @param {Object} point
 * @return Point object with attributes x and y.
 */
function pixelToTile(point) {
    var realx = point.x/16;
    var realy = point.y/16;	
    if(parseInt(realx) < realx) { realx = parseInt(realx)+1; }	
    if(parseInt(realy) < realy) { realy = parseInt(realy)+1; }
    return {x:realx, y:realy};
}


/**
 * Function tileToPixel
 * @param {Array} tile
 * @return
 */
function tileToPixel(tile) {
    var outputPoint = [];
    outputPoint[0] = (tile[0]*16)-8; //calibrates to center of tile
    outputPoint[1] = (tile[1]*16)-8; //again
    return {x:outputPoint[0], y:outputPoint[1]};
}


/**
 * Function sendMessage
 * @param {Object} event
 */
function sendMessage(event) {
  //Verify if user pressed ENTER
  if(event.keyCode == 13) {
    var message = encodeURIComponent($('edt_message').value);
    if (message !== '') {
      new Ajax.Request('d5power.php', {method: 'get', parameters: 'action=send_chat&message='+message, onComplete:
        function(result) {
          if (result.responseText == 'OK') {
            $('edt_message').value = '';
            addToHistory(myCharacter.characterId,myCharacter.name, decodeURIComponent(message));
          }
        }
      });
    }
  }
}


/**
 * Function addToHistory
 * @param {String} charName
 * @param {String} message
 */
function addToHistory(id,charName,message) {
  $('chat_history').innerHTML += charName+': '+message+'<br>';
  $('chat_history').scrollTop = $('chat_history').scrollHeight;
  var face='';
	switch(message)
	{
		case '呵呵':
		case '笑':
		case '哈哈':
			face = 'xiao';
			break;
		case '恩':
		case '嗯':
			face = 'en';
			break;
		case '汗':
			face = 'han';
			break;
		case '好':
			face = 'hao';
			break;
		case '好样的':
		case '厉害':
		case '高手':
			face = 'haoyangde';
			break;
		case '嘿嘿':
		case '奸笑':
			face = 'jianxiao';
			break;
		case '啊':
		case '靠':
			face = 'kao';
			break;
		case '哭':
			face = 'ku';
			break;
		case '亲':
			face = 'qin';
			break;
		case '也':
			face = 'ye';
			break;
	}
	
	if(face!='')
	{
		$('faceBox'+id).innerHTML = "<img src='../pictures/face/"+face+".gif'>";
		$('faceBox'+id).style.display='block';
	}else{
  		$('chatBox'+id).style.display = "block";
		$('chatBox'+id).innerHTML = "<span>"+message+"</span>";
	}

	setTimeout("hiddenChatMessage('"+id+"')",5000);
}

function hiddenChatMessage(id)
{
	$('chatBox'+id).innerHTML = '';
	$('chatBox'+id).style.display='none';
	
	$('faceBox'+id).innerHTML = '';
	$('faceBox'+id).style.display='none';
}



/**
 * Start the character walking.
 */
D5MapEvent = function(event) {

	if(!ctrlholded && allowClick)
	{
		if (!myCharacter.walking)
		{
			var mousePoint = captureMousePoint(event);
			if ((isNaN(mousePoint.x)) || (isNaN(mousePoint.y)))
			{
				alert('Sorry, D5Power Engine do not run in your browser yet. Try one of these browsers: Mozilla Firefox 1.5+, Microsoft Internet Explorer 5+ or Konqueror 3.5+');
				return;
			}
			mousePoint.x -= mapOffset.x;
			mousePoint.y -= mapOffset.y;
			var goalPoint = pixelToTile(mousePoint);
			goalPoint = [goalPoint.x, goalPoint.y];
			var startPoint = pixelToTile(myCharacter.actualPosition);
			startPoint = [startPoint.x, startPoint.y];
			var path = AStar(actualMap.collisionPoints, startPoint, goalPoint, 'DiagonalFree');
		
			if (path.length > 0 && !myCharacter.busy)
			{
				myCharacter.pointsToWalk = path;
				myCharacter.walking = true;
				new Ajax.Request('d5power.php', {method: 'get', parameters: 'action=walk&posx='+goalPoint[0]+'&posy='+goalPoint[1], onComplete:
					function(result) {
						//TODO: validations from server
					}
				});
			}
		
			//Change map? (waypoint)
			if(actualMap.waypoints.isActive())
			{
			myCharacter.changeMap = true;
			}
		}else{
			gameConsole('您正在移动中，请不要连续点击');
		}
	}
};

/**
* Function changeMap
* @description Used for character to walk along the maps.
*/
changeMap = function() {
  if(!myCharacter.busy) {
    myCharacter.busy = true;
    new Ajax.Request('d5power.php', { method: 'get', parameters: 'action=changeMap', onComplete:
      function(result) {
        if(result.responseText == 'OK') changeMapDo();
        myCharacter.busy = false;
      }
    });
  }
	return;
}

changeMapDo = function(){
	$('characters_layer').innerHTML = '';
	$('up_layer').innerHTML = '';
	initEngine();
}
/**
 * Function initEngine
 * @description Used to initialize the Engine.
 */
initEngine = function() {
	if (mLoop != null)
	{
		window.clearInterval(mLoop);
	}
	if (eventsLoop != null)
	{
		window.clearInterval(eventsLoop);
	}
	
	if(monsterLoop!=null)
	{
		window.clearInterval(monsterLoop);
	}
	
	removeChildNodes($('events_layer'));
	removeChildNodes($('characters_layer'));
	
	actualMap = new Map();
    actualMap.load();
	
    charactersOnScreen = new characterList(null);
	monstersOnScreen = new monsterList(null);
    loadCharacters('myLoggedCharacter');
    loadCharacters('otherCharacters');
    
    mLoop = window.setInterval('mainLoop()',70);
	monsterLoop = window.setInterval('monsterWalk()',40000);
	eventsLoop = window.setInterval('getNewEvents()', 2000);
}


/**
 * 
 */
mainLoop = function() {	
    for(var i=0; i<charactersOnScreen.length(); i++) {
        var character = charactersOnScreen.getByIndex(i);
        if(character.walking) {
            character.walk();
        }
    }
	for(var i=0;i<monstersOnScreen.length();i++)
	{
		var monster = monstersOnScreen.getByIndex(i);
		if(monster.walking) {
            monster.walk();
        }
	}
}

monsterWalk = function(){
	for(var i=0;i<monstersOnScreen.length();i++)
	{
		try{
			var monster = monstersOnScreen.getByIndex(i);
			if (!monster.walking)
			{
				var randpos = getRandomAvailableTile();
				var targetPoint = {x:randpos.x,y:randpos.y};
				goalPoint = [targetPoint.x, targetPoint.y];
				var startPoint = pixelToTile(monster.actualPosition);
				startPoint = [startPoint.x, startPoint.y];
				var path = AStar(actualMap.collisionPoints, startPoint, goalPoint, 'DiagonalFree');
				
				if (path.length > 0 && !myCharacter.busy)
				{
					monster.pointsToWalk = path;
					monster.walking = true;
				}
			}
		}catch(e){
			continue;
		}
	}
}


/**
 * 
 */
getNewEvents = function() {
	new Ajax.Request(
            'd5power.php', {
            method: 'get',
            parameters: 'action=getNewEvents',
            onComplete:
			  function(result) {
                var jsonObj = eval("(" + result.responseText + ")");
				//Check for characters entering in your map
				if(jsonObj['entermap'].length > 0)
				{
					for(var i=0; i<jsonObj['entermap'].length; i++)
					{
						var new_char = arrayToCharacter(jsonObj['entermap'][i]);
						charactersOnScreen.add(new_char);
					}
				}
				//Check for characters leaving you map
				if(jsonObj['outmap'].length > 0)
				{
					for(var i=0; i<jsonObj['outmap'].length; i++)
					{
						charactersOnScreen.remove(jsonObj['outmap'][i]);
					}
				}
				//Parsing chat messages
				if(jsonObj['chat'] != null) {
					for(var i=0; i<jsonObj['chat'].length; i++) {
						addToHistory(jsonObj['chat'][i]['cid'],charactersOnScreen.getById(jsonObj['chat'][i]['cid']).name,
						jsonObj['chat'][i]['chatmsg']);
					}
				}
				
				if(jsonObj['movements'] != null) {
					for(var i=0; i<jsonObj['movements'].length; i++) {
						//alert(jsonObj['movements'][i]['cid']);
						var c = charactersOnScreen.getById(jsonObj['movements'][i]['cid']);
						var goalPoint = [parseInt(jsonObj['movements'][i]['posx']), parseInt(jsonObj['movements'][i]['posy'])];
						
						var startPoint = pixelToTile(c.actualPosition);
							startPoint = [startPoint.x, startPoint.y];
						var path = AStar(actualMap.collisionPoints, startPoint, goalPoint, 'DiagonalFree');
						
						if (path.length > 0) {
					    	c.pointsToWalk = path;
							c.walking = true;
						}
					}
             	}
				
				
				//Check for new battle calls
				if(jsonObj['battle_event'].length > 0)
				{
					//gameConsole(jsonObj['battle_event']);
					if(jsonObj['battle_event'][0] == 'recused')
					{
						closeDialog();
						return;
					}
					if(jsonObj['battle_event'][0] == 'DIE')
					{
						hideBattleScreen();
						addToHistory(0,'<font color="#FF0000">系统提示',rival.name+'将你杀死了</font>');
						return;
					}
					if(jsonObj['battle_event'][0] == 'OPP')
					{
						makeBattleTurn(false);
						showBattleScreen();
						return;
					}
					if(jsonObj['battle_event'][0] == 'ME')
					{
						makeBattleTurn(true);
						showBattleScreen();
						showFightMessage(jsonObj['battle_event'][1],'OPP');
					}
					if(jsonObj['battle_event'][0]=='invite')
					{
						var opponent_id = jsonObj['battle_event'][1];
						makeBattleTurn(jsonObj['battle_event'][2]);
						
						var opponent = charactersOnScreen.getById(opponent_id);
						rival = opponent;
						alert_battle(opponent);
					}
				}
			}
		});		
	return;
}

function makeBattleTurn(ismy)
{
	if(ismy)
	{
		$('action_atacar').innerHTML = '<img style="width: 32px; height: 32px;" alt="" src="../pictures/fight/attack.jpg" onClick="attack();">';
		$('action_defender').innerHTML = '<img style="width: 32px; height: 32px;" alt="" src="../pictures/fight/defend.jpg" onClick="defend();">';
	}else{
		$('action_atacar').innerHTML = '<img style="width: 32px; height: 32px;" alt="" src="../pictures/fight/attack_pb.jpg">';
		$('action_defender').innerHTML = '<img style="width: 32px; height: 32px;" alt="" src="../pictures/fight/defend_pb.jpg">';
	}
}


function alert_battle(opponent) {
  dialog('infight', '"'+opponent.name+'"向您发起挑战！您要接受吗？');
  $('dialog_buttons').innerHTML = '<p style="text-align: center;"><img onclick="acceptBattle();" src="../pictures/dialog/button_yes.gif">&nbsp;&nbsp;'+
                                  '<img onclick="rejectBattle();" src="../pictures/dialog/button_no.gif"></p>';
  return;
}


function acceptBattle()
{
	var dialog = $('dialog_container');
	dialog.style.display = 'none';
	new Ajax.Request
	(
		'd5power.php', 
		{
			method: 'get', 
			parameters: 'action=acceptBattle',
			onComplete: function(result){
				if(result.responseText == 'OK') {
					showBattleScreen();
				}else {
					alert(result.responseText);
				}
			}
		}
	);
}


function rejectBattle() {
  var dialog = $('dialog_container');
  dialog.style.display = 'none';
  new Ajax.Request('dotk.php', {method: 'get', parameters: 'action=rejectBattle'});
  return;
}


function showBattleScreen() {
  var battle_screen = $('battle_screen');
  //if(!battle_screen.style.display == 'block') {
  $('portrait').innerHTML = '<img style="width: 48px; height: 48px;" alt="" src="../pictures/charsets/'+myCharacter.avatar+'_face.png">';
  $('my_name').innerHTML = myCharacter.name;
  $('my_hp').innerHTML = myCharacter.hp;


  $('rival_portrait').innerHTML = '<img style="width: 48px; height: 48px;" alt="" src="../pictures/charsets/'+rival.avatar+'_face.png">';

  $('rival_name').innerHTML = rival.name;

  $('rival_hp').innerHTML = rival.hp;

  battle_screen.style.display = 'block';
  //}
  closeDialog();
  return;
}

function hideBattleScreen()
{
	makeBattleTurn(false);
	var battle_screen = $('battle_screen');
	battle_screen.style.display = 'none';
	return;
}

function showFightMessage(data,type)
{
	if(data==undefined) return;
	var result = data[0].message;
	var hurt = data[0].damage;
	var msg;
	
	if(type=='ME')
	{
		target = rival;
		atker = '你';
		beatker = rival.name;
	}else{
		target = myCharacter;
		atker = rival.name;
		beatker = '你';
	}
	
	switch(result)
	{
		case 'LUCK':
			
			msg=beatker+"幸运地躲过攻击<br>";
			break;
		
		case 'MISS':
			
			msg=beatker+'未命中<br>';
			break;
		
		case 'ATK':
			
			msg=atker+'对'+beatker+'攻击造成了'+hurt+'点伤害<br>';
			break;
		
		case 'CRI':
			
			msg=atker+'对'+beatker+'会心一击造成了'+hurt+'点伤害<br>';
			break;
	}
	
	target.hp -= hurt;
	$('battle_history').innerHTML+=msg;
	
}


function inviteToBattle() {
  var character_id = lastOpponentClicked;
  if(character_id==myCharacter.characterId)
  {
	  gameConsole('挑战自己值得敬佩，但您不能向自己挥剑哦！');
	  return;
  }
  rival = charactersOnScreen.getById(character_id);
  new Ajax.Request('d5power.php', {
    method: 'get',
    parameters: 'action=inviteToBattle&opponent='+character_id,
    onComplete: function(result) {
      if(result.responseText == 'OK') {
        dialog('infight','已发送战斗请求，请等待对方响应...');
        $('dialog_buttons').innerHTML = '';
        //  '<p style="text-align: center; margin: 0; ">'+
        //  '<img onclick="acceptBattle();" src="../pictures/button_yes.gif">&nbsp;&nbsp;'+
        //  '<img onclick="rejectBattle();" src="../pictures/button_no.gif"></p>';
      }
      else {
        gameConsole(result.responseText);
      }
    }
  });
  $('ingame_menu').style.display = 'none';
}

/**
 * Function to open a auto closed message window
 *
 *
 */
gameConsole = function(msg) {
  var obj = $('console');
  obj.innerHTML = msg;
  obj.style.display = 'block';
  window.setTimeout("$('console').style.display = 'none';",2000);
  return;
}

/**
 *	Function to open the dialog window
 *
 *
 */
function dialog(icon, msg) {
  var iconBox = $('dialog_icon');
  iconBox.innerHTML = '<img src="../pictures/dialog/'+icon+'.gif" alt="">';

  var message = $('dialog_text');
  message.innerHTML = msg;

  var dialog = $('dialog_container');
  dialog.style.display = 'block';
  return;
}

function closeDialog()
{
	try{
		$('dialog_container').style.display='none';
	}catch(e){}
}
/**
 * Function loadCharacters
 * @return
 * @description Used to load all characters on the map.
 */
function loadCharacters(who) {
    
    switch(who) {
                
        case 'myLoggedCharacter':
            new Ajax.Request(
            'd5power.php', {
            method: 'get',
            parameters: 'action=getMyLoggedCharacter',
            onComplete: function(result) {
                            var jsonString = eval("(" + result.responseText + ")");
                            //set the global reference to my character.
                            myCharacter = arrayToCharacter(jsonString);
                            charactersOnScreen.add(myCharacter);
							myCharacter.setupUserinfo();
            }});
        break
        
        case 'otherCharacters':
            new Ajax.Request(
            'd5power.php', {
            method: 'get',
            parameters: 'action=getOtherCharacters',
            onComplete: function(result) {
                            var jsonObj = eval("(" + result.responseText  + ")");
                            for(i=0; i<jsonObj.length; i++) {
                                charactersOnScreen.add(arrayToCharacter(jsonObj[i]));
                            }
            }});
        break
    }
}

function callNpcEvent(event)
{
	if(event.srcElement)
	{
		var target = event.srcElement;
	}else{
		var target = event.target;
	}

	nowCalledNpc = target;
	new Ajax.Request(
		'd5power.php', {
		method: 'get',
		parameters: 'action=getNpcEvent&npcid='+target.id+'&rand='+Math.random(),
		onComplete: function(result) {
						var npcEvent = eval("(" + result.responseText + ")");
						//set the global reference to my character.
						setChatWindow(); // Hidden chat box when chat with npc
						$('npc_name').innerHTML = nowCalledNpc.name;
						$('npc_say').innerHTML = npcEvent.info;
						$('npcDialogShow').innerHTML = "<img src=\"../pictures/npc/"+nowCalledNpc.avatar+"_show.gif\">";
						$('npc_option').innerHTML = "<a onclick=\""+npcEvent.callbackfunction+";return false;\" href='#'>"+npcEvent.callbackname+"</a>";
						$('npc_option').innerHTML+="<a onclick='closeNpcEvent();return false;' href='#'>关闭</a>";
						$('npcDialogBox').style.display='block';
		}});
}

function closeNpcEvent()
{
	nowCalledNpc = null;
	$('npc_option').innerHTML = '';
	$('npc_name').innerHTML = '';
	$('npc_say').innerHTML = '';
	$('npcDialogBox').style.display='none';
	setChatWindow();
}

/** 
 * @description jsonToCharacter function is used to
 * convert a JSONArray format to a DotK Character instance.
 * @param {Object} JSONArray
 * @return {Character} outputCharacter
 */
function arrayToCharacter(jsonObject) {
    outputCharacter = new Character(
    jsonObject.cid,
    jsonObject.charactername,
    tileToPixel({0:jsonObject.posx, 1:jsonObject.posy}),
    jsonObject.avatar,
	jsonObject.gender,
	jsonObject.hp,
	jsonObject.str,
	jsonObject.dex,
	jsonObject.int,
	jsonObject.vit,
	jsonObject.agi,
	jsonObject.attack,
	jsonObject.defense,
	jsonObject.level,
	jsonObject.xp
	);
	/*
	jsonObject.money,
    jsonObject.xp,
    jsonObject.lvl,
    
    jsonObject.dexterity,
    jsonObject.inteligence,
    jsonObject.strength,
    jsonObject.vitality,
    jsonObject.wisdom,
	*/
    return outputCharacter;
}

/**
 *	Description jsonToMonster function is used to
 *	convert a JSONArray format to a D5Power DotK Monster instance.
 *	@param {Object} JSONArray
 *	@return {Monster} outPutMonster
 */

function arrayToMonster(jsonObject,p)
{
	var randpos = getRandomAvailableTile();
	outputMonster = new Monster(
		p,						
		jsonObject.monster_id,
		jsonObject._name,
		tileToPixel({0:randpos.x, 1:randpos.y}),
		jsonObject._avatar,
		jsonObject._str,
		jsonObject._dex,
		jsonObject._agi,
		jsonObject._int,
		jsonObject._vit,
		jsonObject._level,
		jsonObject._atk,
		jsonObject._def
	);
	
	return outputMonster;
}
// 随机生成位置
function getRandomAvailableTile()
{
	var randx=Math.floor(GADX*Math.random());
	var randy=Math.floor(GADY*Math.random());
	
	result = {x:randx,y:randy};
	try
	{
		if(actualMap.collisionPoints[randy][randx]==1 || randx>=(GADX-2) || randy>=(GADY-2) || randx<=2 || randy<=2)
		{
			result=getRandomAvailableTile();
		}
	}catch(e){
		result=getRandomAvailableTile();
	}
	
	return result;
}

/**
 * Function captureMousePoint
 * @description Capture actual mouse position on screen.
 * @param {Object} event
 */
function captureMousePoint(event) {
  var x,y;
  
  if (Prototype.Browser.IE) {
    $x = window.event.clientX + document.documentElement.scrollLeft
      + document.body.scrollLeft;
    $y = window.event.clientY + document.documentElement.scrollTop
      + document.body.scrollTop;
  }
  if (Prototype.Browser.Gecko) {
    $x = event.clientX + window.scrollX;
    $y = event.clientY + window.scrollY;
  }
  return {x:$x, y:$y};
}


/**
 * Function showCoordinates
 * @description For debug only.
 */
function showCoordinates(event) {
    var mouse = captureMousePoint(event);
    mouse.x -= mapOffset.x;
    mouse.y -= mapOffset.y;
    var tile = pixelToTile(mouse);
    document.getElementById('debug').innerHTML = 'Debug info: coordinates ('+mouse.x+','+mouse.y+')   tile ('+tile.x+','+tile.y+')';
}

/**
 * Function removeChildNodes
 * @description clear all elements content from a Object.
 * @param {Object} el
 */
function removeChildNodes(el)
{
	while (el.childNodes[0])
	{
		el.removeChild(el.childNodes[0]);
	}
}

/**
 *
 *
 *
 */
 
function setChatWindow()
{
	var status = $('chat_div').getAttribute('status');
	if(status=='hidden') return;
	$('chat_div').style.display = $('chat_div').style.display=='' ? 'none' : '';
}